﻿using System;
using System.Windows.Forms;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using Microsoft.Win32;
using Microsoft.VisualStudio.Tools.Applications.Runtime;
using Word = Microsoft.Office.Interop.Word;
using Office = Microsoft.Office.Core;
using Microsoft;
using System.Drawing;
using CloudOfficeEngine;
using GoogleConnector;
using Utilities;
using UILibrary;

namespace OfficeInCloudWord2003Addin2
{
    public partial class ThisAddIn
    {
        private struct paneInfo
        {
            public CustomActionPane pane;
            public MyGDocsForm myGDocsForm;

            public paneInfo(CustomActionPane _pane, MyGDocsForm _myGDocsForm)
            {
                pane = _pane;
                myGDocsForm = _myGDocsForm;
            }
        }

        Word.Application m_app;
        private Dictionary<IntPtr, paneInfo> m_panesCollection = new Dictionary<IntPtr, paneInfo>();
        private CommandBar m_cmdBar;
        private COE m_Engine;
        private WordLocalView m_LocalView;
        private Connector m_RemoteConnector;
        private bool DisabledMode = true;
        private TraceWrapper m_traceWrapper;
        private DbOperations m_dbOperations;
        Office.CommandBarButton m_showMenu;
        Office.CommandBarButton m_updateMenu;
        Office.CommandBarButton m_aboutMenu;
        public Update m_updateChecker;
        private int m_paneWidth = 313;
        private SnapshotManager m_snapshot;

        private void communicationSetup()
        {
            m_LocalView = new WordLocalView(this.Application, m_dbOperations);
            m_RemoteConnector = new Connector();
            m_Engine = new COE(m_LocalView, m_RemoteConnector);
        }

        private void checkForLicense()
        {
            //First Run
            RegistryKey kHKCU = Registry.CurrentUser;
            RegistryKey kFirstRun;
            try
            {
                kFirstRun = kHKCU.OpenSubKey("Software\\UpriseApps\\OfficeInCloudExcel2007", true);
                if (kFirstRun == null)
                {
                    kFirstRun = kHKCU.CreateSubKey("Software\\UpriseApps\\OfficeInCloudExcel2007", RegistryKeyPermissionCheck.ReadWriteSubTree);
                    kFirstRun.SetValue("FirstRun", 1);
                    //MessageBox.Show("Office In Cloud for Google Docs (Excel 2007) was not properly installed. \n Please contact Uprise Apps support.", "Office In Cloud Error Message");
                }
                else
                {
                    if (kFirstRun.GetValue("FirstRun").ToString().Equals("1"))
                    {
                        //Registration Wizard
                        Registration regForm = new Registration(m_dbOperations, System.Reflection.Assembly.GetEntryAssembly());
                        if (DialogResult.OK == regForm.ShowDialog())
                        {
                            DisabledMode = false;
                        }
                    }
                    else DisabledMode = false;
                }
            }
            catch (Exception ex)
            {
                Utilities.TraceWrapper.LogException("ThisAddIn_Startup error: " + ex.Message, ex);

                MessageBox.Show("Office In Cloud for Google Docs (Excel 2007) was not properly installed. \n Please contact Uprise Apps support.", "Office In Cloud Error Message");
            }
        }

        private void showAbout(Office.CommandBarButton Ctrl, ref bool CancelDefault)
        {
            AboutBox about = new AboutBox(Assembly.GetExecutingAssembly());
            about.ShowDialog();
        }

        private void checkForUpdates(Office.CommandBarButton Ctrl, ref bool CancelDefault)
        {
            m_updateChecker.checkForUpdates(Properties.Resources.AppUpdateName,
                                            System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString());
        }

        private void showActionPane(Office.CommandBarButton Ctrl, ref bool CancelDefault)
        {
            constructActionPane(m_app.ActiveWindow.Caption + Properties.Resources.CaptionSuffix);
        }

        private void ThisAddIn_Startup(object sender, System.EventArgs e)
        {
            m_app = this.Application;

            CommonOperations.initPaths("\\Uprise Apps\\Word2003og.txt", 
                                        "\\Uprise Apps\\Info.mdb",
                                        System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase);

            m_traceWrapper = new TraceWrapper();
            m_traceWrapper.initTraceListener();
            m_traceWrapper.traceSystemInfo(this.Application.Version,
                                            System.Reflection.Assembly.GetExecutingAssembly().GetName().ToString());

            try
            {
                m_updateChecker = new Update();
                //m_updateChecker.checkForUpdates(Properties.Resources.AppUpdateName);

                m_dbOperations = new DbOperations(new DbManager(Utilities.Path.dbPath));
                m_snapshot = new SnapshotManager();

                checkForLicense();

                communicationSetup();

                //build UI
                setupActionPane();
                constructActionPane("Microsoft Word");

                m_cmdBar = new CommandBar();
                m_cmdBar.buildMenuBar((Office.CommandBar)Application.CommandBars.ActiveMenuBar,
                                        new Office._CommandBarButtonEvents_ClickEventHandler(showActionPane),
                                        new Office._CommandBarButtonEvents_ClickEventHandler(checkForUpdates),
                                        new Office._CommandBarButtonEvents_ClickEventHandler(showAbout));

                m_app.DocumentOpen += new Microsoft.Office.Interop.Word.ApplicationEvents4_DocumentOpenEventHandler(m_app_DocumentOpen);
                m_app.DocumentBeforeClose += new Microsoft.Office.Interop.Word.ApplicationEvents4_DocumentBeforeCloseEventHandler(m_app_DocumentBeforeClose);
                ((Microsoft.Office.Interop.Word.ApplicationEvents4_Event)m_app).NewDocument += new Microsoft.Office.Interop.Word.ApplicationEvents4_NewDocumentEventHandler(m_app_DocumentNew);
            }
            catch (System.Exception ex)
            {
                TraceWrapper.LogException("addin startup error" + ex.Message, ex);
            }
        }

        //in the Word2003 it's necessary to create special key in the registry
        //in the cases the taskpane will not be displayed in new or opened documents
        private void setupActionPane()
        {
            RegistryKey kHKCU = Registry.CurrentUser;
            RegistryKey kValue;
            try
            {
                kValue = kHKCU.OpenSubKey("Software\\Microsoft\\Office\\11.0\\Common\\General", true);
                kValue.SetValue("DoNotDismissFileNewTaskPane", 1, RegistryValueKind.DWord);
            }
            catch (Exception ex)
            {
                Utilities.TraceWrapper.LogException("Can't set required key: " + ex.Message, ex);
            }
        }

        private void cleanUpPaneInfo()
        {
            //MessageBox.Show("Clean up");
            string activeWndCaption = m_app.ActiveWindow.Caption + Properties.Resources.CaptionSuffix;
            IntPtr hAppWnd = Win32Declaration.FindWindow("OpusApp", activeWndCaption);

            if (m_panesCollection.ContainsKey(hAppWnd))
                m_panesCollection.Remove(hAppWnd);
        }

        void m_app_DocumentBeforeClose(Microsoft.Office.Interop.Word.Document Doc, ref bool Cancel)
        {
            int chars = 256;
            System.Text.StringBuilder buff = new System.Text.StringBuilder(chars);
            IntPtr handle = Win32Declaration.GetForegroundWindow();

            if (m_panesCollection.ContainsKey(handle))
            {
                m_panesCollection[handle].pane.release();
                m_panesCollection.Remove(handle);
            }
        }

        void m_app_DocumentNew(Microsoft.Office.Interop.Word.Document Doc)
        {
            //MessageBox.Show("new doc");
            constructActionPane(Doc.ActiveWindow.Caption + Properties.Resources.CaptionSuffix);
        }

        void m_app_DocumentOpen(Microsoft.Office.Interop.Word.Document Doc)
        {
            //MessageBox.Show("open doc");
            constructActionPane(Doc.ActiveWindow.Caption + Properties.Resources.CaptionSuffix);
        }

        private void constructActionPane(string caption)
        {
            //MessageBox.Show("construct");
            //create our own window at the top of command bar "Task Pane"
            IntPtr hAppWnd = IntPtr.Zero;
            IntPtr hPaneWnd = IntPtr.Zero;
            lookForHandles(caption, out hAppWnd, out hPaneWnd);

            if ((hAppWnd != IntPtr.Zero) && (hPaneWnd != IntPtr.Zero) && (!m_panesCollection.ContainsKey(hAppWnd)))
            {
                MyGDocsForm myGDocsForm = new MyGDocsForm(m_LocalView, DisabledMode, m_dbOperations, m_traceWrapper, m_snapshot, Google.Documents.Document.DocumentType.Document, System.Reflection.Assembly.GetExecutingAssembly());

                CustomActionPane pane = new CustomActionPane(hAppWnd, hPaneWnd);
                pane.buildActionPane();
                pane.m_actionPane.m_release += this.cleanUpPaneInfo;

                pane.m_actionPane.Controls.Add(myGDocsForm);
                myGDocsForm.Visible = true;

                m_panesCollection.Add(hAppWnd, new paneInfo(pane, myGDocsForm));

                m_snapshot.applySnapshot("clearLogin", myGDocsForm);
                //MessageBox.Show("There is handles");
            }
            //else
              //  MessageBox.Show("No handles");
        }

        private Office.CommandBar getCommandBar(string name)
        {
            Office.CommandBar cmdBar = null;
            foreach (Office.CommandBar cmd in m_app.CommandBars)
            {
                if (cmd.Name == name)
                {
                    cmdBar = cmd;
                    break;
                }
            }

            return cmdBar;
        }

        private void resizeActionPane()
        {
            Office.CommandBar cmdPane = getCommandBar("Task Pane");

            if (cmdPane != null)
            {
                cmdPane.Position = Office.MsoBarPosition.msoBarRight;
                cmdPane.Width = m_paneWidth;
            }
        }


        private void lookForHandles(string caption, out IntPtr hAppWnd, out IntPtr hPaneWnd)
        {
            resizeActionPane();

            // Obtain the handle of the active window.
            int chars = 256;
            System.Text.StringBuilder buff = new System.Text.StringBuilder(chars);

            hAppWnd = Win32Declaration.FindWindow("OpusApp", caption);
            hPaneWnd = Win32Declaration.FindWindowEx(hAppWnd, IntPtr.Zero, "MsoCommandBarDock", "MsoDockRight");
        }

        private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
        {
            //necessary to manualy remove even temporary command bars
            m_cmdBar.removeBar((Office.CommandBar)Application.CommandBars.ActiveMenuBar);

            //restore wnd proc
            foreach (var pair in m_panesCollection)
                pair.Value.pane.release();

            // Flush the output.
            Trace.WriteLine("");
            Trace.WriteLine("");
            Trace.WriteLine("");
            m_traceWrapper.shutdownTraceListener();
        }

        #region VSTO generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InternalStartup()
        {
            this.Startup += new System.EventHandler(ThisAddIn_Startup);
            this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
        }

        #endregion
    }

}
